package com.cty.fourteenthDay;

import java.util.ArrayList;
import java.util.Arrays;

/*
 * 给定一个 m x n 的矩阵，如果一个元素为 0 ，
 * 则将其所在行和列的所有元素都设为 0 。请使用 原地 算法
 *
 * 在计算机科学中，一个原地算法（in-place algorithm）是一种使用小的，固定数量的额外之空间来转换资料的算法。
 * 当算法执行时，输入的资料通常会被要输出的部分覆盖掉。不是原地算法有时候称为非原地（not-in-place）
 * 或不得其所（out-of-place）
 * */
public class Q_18 {
    public static void main(String[] args) {
        int[][] matrix = {{1,1,1},{1,0,1},{1,1,1}};
        setZeroes(matrix);
        for (int[] m : matrix) {
            System.out.println(Arrays.toString(m));
        }
    }

    // 暴力算法 时间复杂度O(Mn) 空间复杂度O(n)
    public static void setZeroes(int[][] matrix) {
        if (matrix == null || matrix.length == 0) return;
        ArrayList<int[]> flag = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
             for (int j = 0;j < matrix[i].length;j++) {
                 if (matrix[i][j] == 0) {
                     flag.add(new int[]{i,j});
                 }
             }
        }
        //遍历标记
        for (int[] f : flag) {
            Arrays.fill(matrix[f[0]],0);
            for (int i = 0;i < matrix.length;i++) {
                matrix[i][f[1]] = 0;
            }
        }
    }


    // 力扣官方题解 使用两个标记数组记录每一行和每一列的是否出现了0 若出现则在将该数据改为0 时间复杂度O(MN) 空间复杂度O(N)
    public static void setZeroes2(int[][] matrix) {
        if (matrix.length == 0) return;
        boolean[] row = new boolean[matrix.length];
        boolean[] col = new boolean[matrix[0].length];
        for (int i = 0;i < matrix.length;i++) {
            for (int j = 0;j < matrix[i].length;j++) {
                if (matrix[i][j] == 0) {
                    row[i] = col[j] = true;
                }
            }
        }

        for (int i = 0;i < matrix.length;i++) {
            for (int j = 0;j < matrix[i].length;j++) {
                if (row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }

    // (力扣官方题解) 使用两个标记变量 使用两个标记变量 标记数组的第一列和第一行是否含有0 若有标记 没有不标记 用数组的第一行和第一列来标记本行和本列是否含有0
    // 时间复杂度O(Mn) 空间复杂度O(1)
    public static void setZeroes3(int[][] matrix) {
        if (matrix.length == 0) return;
        int n = matrix.length,m = matrix[0].length;
        boolean rowZero = false,colZero = false;
        for (int i = 0;i < n;i++){
            if (matrix[i][0] == 0) {
                colZero = true;
            }
        }
        for (int j = 0;j < m;j++) {
            if (matrix[0][j] == 0) {
                rowZero = true;
            }
        }
        for (int i = 1;i < n;i++){
            for (int j = 1;j < m;j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        for (int i = 1;i < n;i++){
            for (int j = 1;j < m;j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        if (rowZero) {
            for (int i = 0;i < m;i++) {
               matrix[0][i] = 0;
            }
        }
        if (colZero) {
            for (int j =0;j < n;j++) {
                matrix[j][0] = 0;
            }
        }
    }

}
